package service

import (
	"github.com/jinzhu/gorm"
	"time"
	"git.oschina.net/fanbuchi/xgggh/oauth2/db"
	"git.oschina.net/fanbuchi/xgggh/oauth2/model"
	"git.oschina.net/fanbuchi/xgggh/oauth2/proto/oauth2"
	 "git.oschina.net/fanbuchi/xgggh/errs"
)

// Authenticate checks the access token is valid
func  Authenticate(token string,client *model.Client) (*model.AccessToken, error) {
	// Fetch the access token from the database
	accessToken := new(model.AccessToken)
	notFound := db.GetDB().
		Where("token = ?", token).
		Where("client_id = ?", client.ID).
		First(accessToken).RecordNotFound()

	// Not found
	if notFound {
		return nil, errs.AccessTokenNotFound
	}

	// Check the access token hasn't expired
	if time.Now().UTC().After(accessToken.ExpiresAt) {
		return nil, errs.AccessTokenExpired
	}

	// Extend refresh token expiration database
	query := db.GetDB().Model(new(model.RefreshToken)).Where("client_id = ?", accessToken.ClientID)
	if accessToken.AccountId>=0 {
		query = query.Where("account_id = ?", accessToken.AccountId)
	} else {
		query = query.Where("account_id IS NULL")
	}
	increasedExpiresAt := gorm.NowFunc().Add(
		time.Duration(model.GetOauthConfig().RefreshTokenLifetime) * time.Second)
	if err := query.UpdateColumn("expires_at", increasedExpiresAt).Error; err != nil {
		return nil, err
	}

	return accessToken, nil
}





// NewRevokeFromAccessToken ...
func  NewRevokeFromAccessToken(accessToken *model.AccessToken,client *model.Client) (*com_xgggh_srv_oauth2.Revoke, error) {
	var revoke = &com_xgggh_srv_oauth2.Revoke{
		Active:    true,
		Scope:     accessToken.Scope,
		TokenType: "Bearer",
		ExpiresAt: accessToken.ExpiresAt.Unix(),
		AccountId:int64(accessToken.AccountId),
		ClientId:client.Key,
	}

	/*if accessToken.ClientID!=0 {
		client := new(model.Client)
		notFound := db.GetDB().Select("key").First(client, accessToken.ClientID).
			RecordNotFound()
		if notFound {
			return nil, errs.ClientNotFound
		}
		revoke.ClientId = client.Key
	}

	if accessToken.UserID!=0 {
		user := new(model.Account)
		notFound := db.GetDB().Select("user_name").First(user, accessToken.UserID).
			RecordNotFound()
		if notFound {
			return nil, errs.UserNotFound
		}
		revoke.UserName = user.UserName
		return revoke,nil
	}*/

	return revoke,nil
}

// NewIntrospectResponseFromRefreshToken ...
func  NewRevokeFromRefreshToken(refreshToken *model.RefreshToken,client *model.Client ) (*com_xgggh_srv_oauth2.Revoke, error) {
	var revoke = &com_xgggh_srv_oauth2.Revoke{
		Active:    true,
		Scope:     refreshToken.Scope,
		TokenType: "Bearer",
		ExpiresAt: refreshToken.ExpiresAt.Unix(),
		AccountId:int64(refreshToken.AccountId),
		ClientId:client.Key,
	}

	/*if refreshToken.ClientID!=0 {
		client := new(model.Client)
		notFound := db.GetDB().Select("key").First(client, refreshToken.ClientID).
			RecordNotFound()
		if notFound {
			return nil, errs.ClientNotFound
		}
		revoke.ClientId = client.Key
	}

	if refreshToken.UserID!=0 {
		user := new(model.Account)
		notFound := db.GetDB().Select("user_name").First(user, refreshToken.UserID).
			RecordNotFound()
		if notFound {
			return nil, errs.ClientNotFound
		}
		revoke.UserName = user.UserName
		return revoke,nil
	}*/

	return revoke,nil
}